4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
11 // You must not remove this notice, or any other, from this software.
15 // NMAKE.C - main module
18 // This is the main module of nmake
26 #include <palstartup.h>
28 int readEnvironmentVars(void);
29 void readMakeFiles(void);
30 void useDefaultMakefile(void);
31 BOOL
filename(const char*, char**);
32 BOOL PALAPI
chkPrecious(DWORD CtrlType
);
33 UCHAR
isPrecious(char*);
34 void removeTrailChars(char *);
38 char *makeStr
; // this make invocation name
40 UCHAR okToDelete
; // do not del unless exec'ing cmd
43 UCHAR fRunningUnderChicago
;
45 extern UCHAR
FIsChicago(void);
48 const char * const builtInTarg
[] = {
56 #if defined(_M_IX86) || defined(_M_MRX000)
78 const char * const bltInCmd0
[] = {
82 #if defined(_M_IX86) || defined(_M_MRX000)
102 // Single colon (":") specifies ordinary rules
103 // Double colon ("::") specifies batch rules
104 const char * const bltInCmd1
[] = {":", "$(CC) $(CFLAGS) /c $<", NULL
};
105 const char * const bltInCmd2
[] = {":", "$(CC) $(CFLAGS) $<", NULL
};
106 const char * const bltInCmd3
[] = {":", "$(CPP) $(CPPFLAGS) /c $<", NULL
};
107 const char * const bltInCmd4
[] = {":", "$(CPP) $(CPPFLAGS) $<", NULL
};
108 const char * const bltInCmd5
[] = {":", "$(CXX) $(CXXFLAGS) /c $<", NULL
};
109 const char * const bltInCmd6
[] = {":", "$(CXX) $(CXXFLAGS) $<", NULL
};
110 #if defined(_M_IX86) || defined(_M_MRX000)
111 const char * const bltInCmd7
[] = {":", "$(AS) $(AFLAGS) /c $*.asm", NULL
};
112 const char * const bltInCmd8
[] = {":", "$(AS) $(AFLAGS) $*.asm", NULL
};
114 #if !defined(_M_IX86)
115 const char * const bltInCmd9
[] = {":", "$(AS) $(AFLAGS) $*.s", NULL
};
117 const char * const bltInCmd10
[] = {":", "$(BC) $(BFLAGS) $*.bas;", NULL
};
118 const char * const bltInCmd11
[] = {":", "$(COBOL) $(COBFLAGS) $*.cbl;", NULL
};
119 const char * const bltInCmd12
[] = {":", "$(COBOL) $(COBFLAGS) $*.cbl, $*.exe;", NULL
};
120 const char * const bltInCmd13
[] = {":", "$(FOR) /c $(FFLAGS) $*.f", NULL
};
121 const char * const bltInCmd14
[] = {":", "$(FOR) $(FFLAGS) $*.f", NULL
};
122 const char * const bltInCmd15
[] = {":", "$(FOR) /c $(FFLAGS) $*.f90", NULL
};
123 const char * const bltInCmd16
[] = {":", "$(FOR) $(FFLAGS) $*.f90", NULL
};
124 const char * const bltInCmd17
[] = {":", "$(FOR) /c $(FFLAGS) $*.for", NULL
};
125 const char * const bltInCmd18
[] = {":", "$(FOR) $(FFLAGS) $*.for", NULL
};
126 const char * const bltInCmd19
[] = {":", "$(PASCAL) /c $(PFLAGS) $*.pas", NULL
};
127 const char * const bltInCmd20
[] = {":", "$(PASCAL) $(PFLAGS) $*.pas", NULL
};
128 const char * const bltInCmd21
[] = {":", "$(RC) $(RFLAGS) /r $*", NULL
};
130 const char * const * const builtInCom
[] = {
138 #if defined(_M_IX86) || defined(_M_MRX000)
142 #if !defined(_M_IX86)
162 // actions: saves the initial global variables in a
163 // block. calls doMake() and then delTempScriptFiles()
171 int status
; // returned by doMake
176 fRunningUnderChicago
= FIsChicago();
181 initMacroTable(macroTable
);
186 if (!filename(_pgmptr
, &makeStr
)) {
191 // set up handler for .PRECIOUS the handler tries to remove the
192 // current target when control-C'd, unless it is "precious"
194 SetConsoleCtrlHandler(chkPrecious
, TRUE
);
196 status
= doMake(argc
, argv
, NULL
);
200 if (!fSlashKStatus
) {
201 status
= 1; // error when slashK specified
210 extern void endNameList(void);
211 extern void addItemToList(void);
212 extern void assignDependents(void);
213 extern void assignBuildCommands(void);
215 // loadBuiltInRules() -- Loads built in Rules to the NMAKE Tables
218 // fInheritUserEnv -- is set to TRUE to inherit CC, AS
221 // Does this by calls to defineMacro(), which calls putMacro(). Since,
222 // fInheritUserEnv is set to TRUE, putMacro() will add to the Environment.
229 const char *tempTarg
;
230 const char * const *tempCom
;
232 char *macroName
, *macroValue
;
234 // We dynamically allocate CC and AS because they need to be freed in a
237 macroName
= makeString("CC");
238 macroValue
= makeString("cl");
239 defineMacro(macroName
, macroValue
, 0);
240 macroName
= makeString("CXX");
241 macroValue
= makeString("cl");
242 defineMacro(macroName
, macroValue
, 0);
243 macroName
= makeString("CPP");
244 macroValue
= makeString("cl");
245 defineMacro(macroName
, macroValue
, 0);
246 macroName
= makeString("AS");
248 macroValue
= makeString("ml");
249 defineMacro(macroName
, macroValue
, 0);
250 macroName
= makeString("BC");
251 macroValue
= makeString("bc");
252 defineMacro(macroName
, macroValue
, 0);
253 macroName
= makeString("COBOL");
254 macroValue
= makeString("cobol");
255 defineMacro(macroName
, macroValue
, 0);
256 macroName
= makeString("FOR");
257 macroValue
= makeString("fl32");
258 defineMacro(macroName
, macroValue
, 0);
259 macroName
= makeString("PASCAL");
260 macroValue
= makeString("pl");
261 defineMacro(macroName
, macroValue
, 0);
262 macroName
= makeString("RC");
263 macroValue
= makeString("rc");
264 defineMacro(macroName
, macroValue
, 0);
265 macroName
= makeString("_NMAKE_VER");
266 macroValue
= makeString(VER_PRODUCTVERSION_STR
);
267 defineMacro(macroName
, macroValue
, 0);
268 macroName
= makeString("MAKE");
269 macroValue
= makeString(makeStr
);
270 // From environment so it won't get exported ; user can reset MAKE
272 defineMacro(macroName
, macroValue
, M_ENVIRONMENT_DEF
|M_WARN_IF_RESET
);
274 for (index
= 0; (tempTarg
= builtInTarg
[index
]); index
++) {
275 name
= makeString(tempTarg
);
276 tempCom
= builtInCom
[index
];
277 // tempCom should now contain a single or double colon
278 assert (tempCom
&& *tempCom
&& **tempCom
== ':');
279 _tcscpy(buf
, *tempCom
);
281 for (tempCom
++; *tempCom
; tempCom
++) {
282 _tcscpy(buf
, *tempCom
);
288 assignBuildCommands();
295 // actions: prints a version message
296 // reads the environment variable MAKEFLAGS
297 // if MAKEFLAGS defined
298 // defines MAKEFLAGS to have that value w/in nmake
299 // sets a flag for each option if MAKEFLAGS defined
300 // else defines the macro MAKEFLAGS to be NULL
301 // parses commandline (adding option letters to MAKEFLAGS)
302 // reads all environment variables
304 // reads makefile(s) (if -e flag set, new definitions in
305 // makefile won't override environment variable defs)
306 // prints information if -p flag
307 // processes makefile(s)
308 // prints information if -d flag and not -p flag (using both
311 // In effect, the order for making assignments is (1 = least binding,
312 // 4 = most binding):
315 // 2) environment (if -e flag, makefile)
316 // 3) makefile (if -e flag, environment)
319 // The user can put anything he wants in the MAKEFLAGS environment variable.
320 // I don't check it for illegal flag values, because there are many xmake
321 // flags that we don't support. He shouldn't have to change his MAKEFLAGS
322 // to use nmake. Xmake always puts 'b' in MAKEFLAGS for "backward com-
323 // patibility" (or "botch") for the original Murray Hill version of make.
324 // It doesn't make sense to use -f in MAKEFLAGS, thus it is disallowed.
325 // It also makes little sense to let the default flags be -r, -p, or -d,
326 // so they aren't allowed in MAKEFLAGS, either.
328 // Even though DOS only uses uppercase in environment variables, this
329 // program may be ported to xenix in the future, thus we allow for the
330 // possibility that MAKEFLAGS and commandline options will be in upper
331 // and/or lower case.
333 // modifies: init global flag set if tools.ini is being parsed...
339 char *parentBlkPtr
// state of parent, restored prior to return
344 // extern char *makeStr; // the initial make invok name
345 char *makeDir
, *curDir
;
348 printf ("DEBUG: In doMake\n");
351 assert(parentBlkPtr
== NULL
);
353 // Load built-ins here rather than in main(). Otherwise in a recursive
354 // make, doMake() will initialize rules to some value which has been
355 // freed by sortRules().
357 inlineFileList
= (STRINGLIST
*)NULL
;
358 makeDir
= makeString("MAKEDIR");
359 curDir
= getCurDir();
360 // Use M_LITERAL flag to prevent nmake from trying to
361 // interpret $ in path as an embedded macro. [DS 14983]
362 defineMacro(makeDir
, curDir
, M_LITERAL
);
364 // TEMPFIX: We are truncating MAKEFLAGS environment variable to its limit
365 // to avoid GP Faults
366 if ((p
= getenv("MAKEFLAGS"))) { // but not MAKEFLAGS
367 _tcsncpy(makeflags
+10, p
, _tcslen(makeflags
+ 10));
370 // fInheritUserEnv is set to TRUE so that the changes made get inherited
372 fInheritUserEnv
= TRUE
;
374 // Simply adding global strings to the macro array
375 // causes problems later when you go to free them
376 // from a recursive $(MAKE). Both the macro name
377 // and the macro's value must be created with
380 defineMacro(makeString("MAKEFLAGS"), makeString(makeflags
+10), M_NON_RESETTABLE
|M_ENVIRONMENT_DEF
);
382 for (;p
&& *p
; p
++) { // set flags in MAKEFLAGS
383 setFlags(*p
, TRUE
); // TRUE says turn bits ON
386 parseCommandLine(--argc
, ++argv
); // skip over program name
389 printf ("DEBUG: Command Line parsed\n");
392 if (!bannerDisplayed
) {
393 displayBanner(); // version number, etc.
396 if (OFF(gFlags
, F1_IGNORE_EXTERN_RULES
)) { // read tools.ini
398 printf ("DEBUG: Read Tools.ini\n");
402 printf ("DEBUG: loadBuiltInRules\n");
406 if (tagOpen("INIT", fName
, makeStr
)) {
408 init
= TRUE
; // tools.ini being parsed
411 printf ("DEBUG: Start Parse\n");
416 printf ("DEBUG: Parsed\n");
418 if (fclose(file
) == EOF
)
419 makeError(0, ERROR_CLOSING_FILE
, fName
);
424 printf ("after tagopen\n");
427 // For XMake Compatibility MAKEFLAGS should always be inherited to the Env
428 // Put copy of makeflags so that the environment can be freed on return
429 // from a recursive make
431 if (PutEnv(makeString(makeflags
)) == -1) {
432 makeError(0, OUT_OF_ENV_SPACE
);
436 printf ("after putenv\n");
440 useDefaultMakefile(); // if no -f makefile given
443 if (readEnvironmentVars() == -1) {
444 makeError(0, OUT_OF_MEMORY
);
446 readMakeFiles(); // read description files
449 printf ("DEBUG: Read makefile\n");
452 currentLine
= 0; // reset line after done
453 sortRules(); // reading files (for error messages)
455 if (ON(gFlags
, F1_PRINT_INFORMATION
)) {
461 // free buffer used for conditional processing - not required now
466 status
= processTree();
468 // We ignore retval from chdir because we cannot do anything if it fails
469 // This accomplishes a 'cd $(MAKEDIR)'.
475 // filename -- filename part of a name
480 // A complete file name is of the form <drive:><path><filename><.ext>. This
481 // function returns the filename part of the name.
483 // Input: src -- The complete file name
484 // dst -- filename part of the complete file name
486 // Output: Returns TRUE if src has a filename part & FALSE otherwise
488 // Assumes: That the file name could have either '/' or '\' as path separator.
491 // Allocates memory for filename part. Function was rewritten to support OS/2
492 // Ver 1.2 filenames.
501 char szFilename
[_MAX_FNAME
]; // The filename part
503 // Split the full pathname to components
504 _splitpath(src
, NULL
, NULL
, szFilename
, NULL
);
506 // Allocate & copy the filename part to the return string
507 *dst
= makeString(szFilename
);
510 return (BOOL
) _tcslen(*dst
);
516 // actions: walks through the list calling parse on each makefile
517 // resets the line number before parsing each file
518 // removes name of parsed file from list
519 // frees removed element's storage space
521 // modifies: file global file pointer (FILE*)
522 // fName global pointer to file name (char*)
523 // line global line number used and updated by the lexer
524 // init global flag reset for parsing makefiles
525 // ( files other than tools.ini )
526 // makeFiles in main() by modifying contents of local pointer (list)
528 // We keep from fragmenting memory by not allocating and then freeing space
529 // for the (probably few) names in the files and targets lists. Instead
530 // we use the space already allocated for the argv[] vars, and use the space
531 // we alloc for the commandfile vars. The commandfile vars that could be
532 // freed here, but they aren't because we can't tell them from the argv[]
533 // vars. They will be freed at the end of the program.
542 for (q
= makeFiles
; q
; q
= q
->next
) { // for each name in list
543 if ((q
->text
)[0] == '-' && !(q
->text
)[1]) {
544 fName
= makeString("STDIN");
547 fName
= makeString(q
->text
);
548 if (!(file
= FILEOPEN(fName
, "rt"))) // open to read, text mode
549 makeError(0, CANT_OPEN_FILE
, fName
);
550 if (!IsValidMakefile(file
))
551 makeError(0, CANT_SUPPORT_UNICODE
, fName
);
554 init
= FALSE
; // not parsing tools.ini
556 if (file
!= stdin
&& fclose(file
) == EOF
)
557 makeError(0, ERROR_CLOSING_FILE
, fName
);
560 // free the list of makefiles
561 freeStringList(makeFiles
);
565 // readEnvironmentVars - Read in environment variables into Macro table
570 // Reads environment variables into the NMAKE macro Table. It walks through envp
571 // using environ making entries in NMAKE's hash table of macros for each string
574 // Assumes: That the env contains strings of the form "VAR=value" i.e. '=' present.
576 // Modifies Globals: fInheritUserEnv - set to false.
579 // environ - Null terminated table of pointers to environment variable
580 // definitions of the form "name=value" (Std C Runtime variable)
583 // If the user specifies "set name=value" as a build command for a target being
584 // built, the change in the environment will not be reflected in nmake's set of
585 // defined variables in the macro table.
601 WCHAR
*envW
= GetEnvironmentStringsW();
606 cbMultiByte
= 1; // need at least the terminating NULL
607 for (tW
= envW
; *tW
; tW
+=cchWideVar
+1) {
608 cchWideVar
= wcslen(tW
);
609 cchWide
+= cchWideVar
+1;
610 cbMultiByte
+= cchWideVar
*2+1;
612 envPtrBase
= (char *)malloc(cbMultiByte
);
614 FreeEnvironmentStringsW(envW
);
617 if (WideCharToMultiByte(CP_ACP
, 0,
619 envPtrBase
, cbMultiByte
,
621 FreeEnvironmentStringsW(envW
);
627 for (envPtr
= envPtrBase
;*envPtr
; envPtr
+=strlen(envPtr
)+1) {
628 if ((t
= _tcschr(envPtr
, '='))) { // should always be TRUE
629 if (!_tcsnicmp(envPtr
, "MAKEFLAGS", 8))
632 // Don't add empty names.
635 // ALLOC: here we make copies of the macro name and value to define
636 macro
= _tcsupr(makeString(envPtr
));
638 value
= makeString(t
+1);
640 fInheritUserEnv
= (BOOL
)FALSE
;
641 if (!defineMacro(macro
, value
, M_ENVIRONMENT_DEF
)) {
642 // ALLOC: here we free the copies if they were not added.
648 FreeEnvironmentStringsW(envW
);
654 // parseCommandLine()
656 // arguments: argc count of arguments in argv vector
657 // argv table of pointers to commandline arguments
659 // actions: reads a command file if necessary
662 // makes a list of makefiles to read
663 // makes a list of targets to build
665 // modifies: makeFiles in main() by modifying contents of parameter
666 // pointer (list) to STRINGLIST pointer
668 // makeTargets in main() by modifying contents of param
669 // pointer (targets) to STRINGLIST pointer
670 // fInheritUserEnv set to TRUE so that user defined changes in the
671 // environment variables get inherited by the Env
673 // nmake doesn't make new copies of command line macro values or environment
674 // variables, but instead uses pointers to the space already allocated.
675 // This can cause problems if the envp, the environment pointer, is accessed
676 // elsewhere in the program (because the vector's strings will contain '\0'
677 // where they used to contain '='). I don't foresee any need for envp[] to
678 // be used elsewhere. Even if we did need to use the environment, we could
679 // access the environ variable or use getenv().
681 // I don't care what the current DOS "switch" character is -- I always
682 // let the user give either.
695 for (; argc
; --argc
, ++argv
) {
696 if (**argv
== '@') { // cmdfile
697 readCommandFile((char *) *argv
+1);
698 // On Unix, '/' can be used when specifying a fully qualified path
699 } else if (**argv
== '-') { // switch
701 if (!_tcsicmp(s
, "help")) {
706 // if '-' and '/' specified then ignores it
708 if (!_tcsicmp(s
, "nologo")) {
709 setFlags(s
[2], TRUE
);
711 } else if (*s
== '?') {
714 } else if (*s
== 'f' || *s
== 'F') {
717 //if '/ffoo' then use 'foo'; else use next argument
718 if (!*mkfl
&& (!--argc
|| !*++argv
|| !*(mkfl
= *argv
))) {
719 makeError(0, CMDLINE_F_NO_FILENAME
);
721 p
= makeNewStrListElement();
722 p
->text
= makeString(mkfl
);
723 appendItem(&makeFiles
, p
);
730 if ((s
= _tcschr(*argv
, '='))) { // macro
732 makeError(0, CMDLINE_NO_MACRONAME
); // User has specified "=value"
735 for (t
= s
++ - 1; WHITESPACE(*t
); --t
)
738 fInheritUserEnv
= (BOOL
)TRUE
;
739 defineMacro(makeString(*argv
+_tcsspn(*argv
, " \t")),
740 makeString( s
+_tcsspn(s
," \t")),
743 removeTrailChars(*argv
);
745 p
= makeNewStrListElement(); // target
746 // use quotes around name if it contains spaces
747 if (_tcschr(*argv
, ' ')) {
748 p
->text
= makeQuotedString(*argv
);
751 p
->text
= makeString(*argv
); // needs to be on heap [rm]
753 appendItem(&makeTargets
, p
);
756 *argv
= NULL
; // so we won't try to free this space
757 } // if processing command file stuff
767 // useDefaultMakefile -- tries to use the default makefile
773 // When no makefile has been specified by the user, set up the default makefile
779 // CMDLINE_NO_MAKEFILE -- 'makefile' does not exist & no target specified
783 // makeTargets -- if 'makefile' does not exist then the first target is removed
785 // makeFiles -- if 'makefile' does not exist then the first target is attached
789 // makeTargets -- the list of targets to be made
792 // Given a commandline not containing a '-f makefile', this is how NMAKE
794 // If ['makefile' exists] then use it as the makefile,
795 // if [(the first target exists and has no extension) or
796 // (if it exists and has an extension for which no inference rule
798 // then use it as the makefile.
807 char nameBuf
[MAXNAME
];
808 struct _finddata_t finddata
;
810 if (!_access("makefile", READ
)) {
811 // if 'makefile' exists then use it
812 p
= makeNewStrListElement();
813 p
->text
= makeString("makefile");
815 } else if (makeTargets
) {
817 s
= makeTargets
->text
;
818 if (_access(s
, READ
) || // 1st target does not exist
819 ((ext
= _tcsrchr(s
, '.'))
820 && findRule(nameBuf
, s
, ext
, &finddata
))) { //has no ext or inf rule
825 makeTargets
= makeTargets
->next
; // one less target
826 makeFiles
= p
; // 1st target is the makefile
827 } else if (OFF(gFlags
, F1_PRINT_INFORMATION
)) {
828 //if -p and no makefile, simply give information ...
829 makeError(0, CMDLINE_NO_MAKEFILE
); // no 'makefile' or target
836 // arguments: line current line number in makefile (or 0
837 // if still parsing commandline)
838 // c letter presumed to be a commandline option
839 // value TRUE if flag should be turned on, FALSE for off
841 // actions: checks to see if c is a valid option-letter
842 // if no, error, halt
843 // if value is TRUE, sets corresponding flag bit
844 // and adds flag letter to MAKEFLAGS macro def
845 // else if flag is resettable, clears corresponding bit
846 // and removes letter from MAKEFLAGS macro def
848 // modifies: flags external resettable-flags
849 // gFlags external non-resettable flags
850 // (MAKEFLAGS nmake internal macrodefs)
852 // Only the flags w/in the "flags" variable can be turned off. Once the
853 // bits in "gFlags" are set, they remain unchanged. The bits in "flags"
854 // are modified via the !CMDSWITCHES directive.
862 // Use lexer's line count. If this gets called w/in mkfil, might be from
863 // directive, which never makes it to the parser, so parser's line count
864 // might be out of sync.
870 extern MACRODEF
* pMacros
;
871 extern STRINGLIST
* pValues
;
874 switch(c
= (char) _totupper(c
)) {
876 arg
= F2_FORCE_BUILD
;
880 fRebuildOnTie
= TRUE
;
884 arg
= F1_CRYPTIC_OUTPUT
;
886 bannerDisplayed
= TRUE
;
890 arg
= F2_DISPLAY_FILE_DATES
;
894 arg
= F1_USE_ENVIRON_VARS
;
899 arg
= F2_IGNORE_EXIT_CODES
;
909 bannerDisplayed
= TRUE
;
917 fDescRebuildOrder
= TRUE
;
921 arg
= F1_PRINT_INFORMATION
;
926 arg
= F1_QUESTION_STATUS
;
931 arg
= F1_IGNORE_EXTERN_RULES
;
940 arg
= F1_TOUCH_TARGETS
;
945 arg
= F2_DUMP_INLINE
;
954 return; // recursive make problem
957 makeError(0, CMDLINE_BAD_OPTION
, d
);
961 pMacros
= findMacro("MAKEFLAGS");
962 pValues
= pMacros
->values
;
966 SET(*f
, arg
); // set bit in flags variable
967 if (c
== 'Q') SET(*f
, F1_CRYPTIC_OUTPUT
);
968 if (!_tcschr(pValues
->text
, c
)) { // don't want to dup any chars
969 if ((s
= _tcschr(pValues
->text
, ' '))) // append ch to MAKEFLAGS
971 if (PutEnv(makeString(makeflags
)) == -1) // pValues->text pts into makeflags
972 makeError(line
, OUT_OF_ENV_SPACE
);
974 } else if (f
== &flags
976 // make sure pointer is valid (we can't change gFlags, except if /Z
978 if ((s
= _tcschr(pValues
->text
, c
))) // adjust MAKEFLAGS
980 *s
= *(s
+1); // move remaining chars over
982 if (PutEnv(makeString(makeflags
)) == -1)
983 makeError(line
, OUT_OF_ENV_SPACE
);
987 // chkPrecious -- handle ^c or ^Break, etc.
989 // Actions: unlink all non-precious files and unrequired scriptFiles
990 // quit with error message (makeError unlinks temp. files)
998 OFF(flags
, F2_NO_EXECUTE
) &&
999 OFF(gFlags
, F1_TOUCH_TARGETS
) &&
1001 _access(dollarAt
, 0x00) && // existence check
1002 !isPrecious(dollarAt
)
1004 if (DeleteFileA(dollarAt
) == FALSE
)
1005 makeError(line
, REMOVED_TARGET
, dollarAt
);
1007 makeError(0, USER_INTERRUPT
);
1021 for (temp
= dotPreciousList
; temp
; temp
= temp
->next
)
1022 if (!_tcsicmp(temp
->text
, p
))
1027 // delScriptFiles -- deletes script files
1032 // Since script files may be reused in the makefile the script files which have
1033 // NOKEEP action specified are deleted at the end of the make.
1035 // Uses Globals: delList -- the list of script files to be deleted
1038 // We ignore the exit code as a result of a delete because the system will
1039 // inform the user that a delete failed.
1049 for (del
= delList
; del
;del
= del
->next
) {
1051 if (ON(flags
, F2_NO_EXECUTE
)) {
1052 printf("\tdel %s\n", del
->text
);
1059 // removeTrailChars - removes trailing blanks and dots
1064 // OS/2 1.2 filenames dictate removal of trailing blanks and periods. This
1065 // function removes them from filenames provided to it.
1067 // Input: szFile - name of file
1070 // This function handles Quoted filenames as well. It maintains the quotes if
1071 // they were present. This is basically for OS/2 1.2 filename support.
1078 char *t
= szFile
+ _tcslen(szFile
) - 1;
1079 BOOL fQuoted
= FALSE
;
1081 if (*szFile
== '"' && *t
== '"') {
1082 // Quoted so set flag
1087 // Scan backwards for trailing characters
1088 while (t
> szFile
&& (*t
== ' ' || *t
== '.'))
1091 // t points to last non-trailing character. It it was quited, add quotes